package gioco;

import elementi.Elemento;
import elementi.ElementoMobile;

import java.util.LinkedList;
import java.util.Iterator;


public class GestoreCollisioni{
	private static GestoreCollisioni singleton = new GestoreCollisioni();
	
	private int altezzaArena;
	private int largezzaArena;
	
	private static final int COLLISIONE_ORIZZONTALE = -1;
	private static final int COLLISIONE_VERTICALE = -2;
	private static final int NO_COLLISIONE = 0;
	private static final int COLLISIONE_ORIZZONTALE_VERTICALE = -3;
	
	public static GestoreCollisioni getSingleton(){
		return singleton;
	}
	
	private GestoreCollisioni(){
		altezzaArena = 0;
		largezzaArena = 0;
	}
	
	public void setDimensioniArena(int larghezza, int altezza){
		this.altezzaArena = altezza;
		this.largezzaArena = larghezza;
	}
	
	//TODO gestire singolarmente le collisioni orizzontali e verticali
	public void controllaCollisioni(ElementoMobile elementoMobile, LinkedList<Elemento> elementi){
		if(verificaCollisioneBordi(elementoMobile) == COLLISIONE_ORIZZONTALE){
			elementoMobile.notificaCollisione(null);
		}
		if(verificaCollisioneBordi(elementoMobile) == COLLISIONE_VERTICALE) {
			elementoMobile.notificaCollisione(null);
		}
		if(verificaCollisioneBordi(elementoMobile) == COLLISIONE_ORIZZONTALE_VERTICALE){
			elementoMobile.notificaCollisione(null);
		}
		
		if(elementi == null) {
			return;
		}
		
		Iterator<Elemento> itel= elementi.iterator();
		while(itel.hasNext()) {
			Elemento eit = itel.next();
			if(verificaCollisione(elementoMobile, eit) == COLLISIONE_ORIZZONTALE_VERTICALE){
				elementoMobile.notificaCollisione(eit);
				eit.notificaCollisione(elementoMobile);
			}
		}
	}
	
	private int verificaCollisione(ElementoMobile elementoMobile, Elemento elemento){
			float xElMobile = getXPlusVel(elementoMobile);
			float yElMobile = getYPlusVel(elementoMobile);
			
			float xEl = elemento.getX() + elemento.getVelocitax();
			float yEl = elemento.getY() + elemento.getVelocitay();
			
			float dist = (xElMobile - xEl) * (xElMobile - xEl) + (yElMobile - yEl) * (yElMobile - yEl);
			if(dist > (elementoMobile.getForma().getRaggio() + elemento.getForma().getRaggio()) * (elementoMobile.getForma().getRaggio() + elemento.getForma().getRaggio())){
				return NO_COLLISIONE;		
			}else{
				return COLLISIONE_ORIZZONTALE_VERTICALE;
			}
	}
	
	private int verificaCollisioneBordi(ElementoMobile elemento){
		float raggio = elemento.getForma().getRaggio();
		boolean collisioneOrizzontale = false;
		boolean collisioneVerticale = false;
		//System.out.println(elemento.getX() +  " "  + elemento.getY() +  " " + raggio + " " + altezzaArena + " " + largezzaArena);
		if(getXPlusVel(elemento) < raggio || getXPlusVel(elemento) > this.largezzaArena - (int)raggio) 
			collisioneOrizzontale = true;
		if(getYPlusVel(elemento) < raggio || getYPlusVel(elemento) > this.altezzaArena - (int)raggio) 
			collisioneVerticale = true;
		
		if(collisioneOrizzontale && collisioneVerticale) 
			return COLLISIONE_ORIZZONTALE_VERTICALE;
		if(collisioneOrizzontale) 
			return COLLISIONE_ORIZZONTALE;
		if(collisioneVerticale) 
			return COLLISIONE_VERTICALE;
		return NO_COLLISIONE;
	}

	private float getYPlusVel(ElementoMobile elemento) {
		return elemento.getY() + elemento.getVelocitay();
	}

	private float getXPlusVel(ElementoMobile elemento) {
		return elemento.getX() + elemento.getVelocitax();
	}
}
